package wecom

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"sync"
	"time"
)

// TokenCache 本地内存缓存接口
type TokenCache interface {
	Get(key string) (string, bool)
	Set(key string, value string, expiration time.Duration)
	Delete(key string)
}

// MemoryCache 内存缓存实现
type MemoryCache struct {
	data map[string]cacheItem
	mu   sync.RWMutex
}

type cacheItem struct {
	value     string
	expiresAt time.Time
}

// NewMemoryCache 创建内存缓存
func NewMemoryCache() *MemoryCache {
	return &MemoryCache{
		data: make(map[string]cacheItem),
	}
}

func (m *MemoryCache) Get(key string) (string, bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	item, exists := m.data[key]
	if !exists {
		return "", false
	}

	// 检查是否过期
	if time.Now().After(item.expiresAt) {
		delete(m.data, key)
		return "", false
	}

	return item.value, true
}

func (m *MemoryCache) Set(key string, value string, expiration time.Duration) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.data[key] = cacheItem{
		value:     value,
		expiresAt: time.Now().Add(expiration),
	}
}

func (m *MemoryCache) Delete(key string) {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.data, key)
}

// WecomConfig 配置结构体（兼容多应用场景）
type WecomConfig struct {
	CorpID      string     // 企业ID（从企业微信后台获取）
	AgentID     int        // 应用AgentID
	AppSecret   string     // 应用Secret
	AgentDomain string     // 代理域名
	ApiDomain   string     // api域名
	TokenCache  TokenCache // 缓存接口
	SafeMode    bool       // 是否启用消息加密
}

// WecomClient 客户端主体
type WecomClient struct {
	config     *WecomConfig
	httpClient *http.Client
	tokenMutex sync.Mutex // Token并发锁
	ctx        context.Context
}

func NewWecomClient(cfg *WecomConfig, ctx context.Context) *WecomClient {
	w := &WecomClient{
		config: cfg,
		httpClient: &http.Client{
			Timeout: 10 * time.Second,
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
			},
		},
		ctx: ctx,
	}

	// 如果没有提供TokenCache，使用默认的内存缓存
	if w.config.TokenCache == nil {
		w.config.TokenCache = NewMemoryCache()
	}

	if w.config.AgentDomain != "" {
		w.config.ApiDomain = w.config.AgentDomain
	} else {
		w.config.ApiDomain = "https://qyapi.weixin.qq.com"
	}
	return w
}

func (wc *WecomClient) getAccessToken() (string, error) {
	cacheKey := fmt.Sprintf("wecom_token_%d", wc.config.AgentID)

	// 先从缓存获取
	if token, exists := wc.config.TokenCache.Get(cacheKey); exists {
		return token, nil
	}

	wc.tokenMutex.Lock()
	defer wc.tokenMutex.Unlock()

	// 调用企业微信API
	url := fmt.Sprintf(
		"%s/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
		wc.config.ApiDomain, wc.config.CorpID, wc.config.AppSecret,
	)

	resp, err := wc.httpClient.Get(url)
	if err != nil {
		return "获取token失败", err
	}

	var result struct {
		ErrCode     int    `json:"errcode"`
		ErrMsg      string `json:"errmsg"`
		AccessToken string `json:"access_token"`
		ExpiresIn   int    `json:"expires_in"`
	}
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return "", err
	}
	if result.ErrCode != 0 {
		return "", errors.New(result.ErrMsg)
	}

	// 缓存Token（提前5分钟过期）
	wc.config.TokenCache.Set(cacheKey, result.AccessToken, time.Duration(result.ExpiresIn-300)*time.Second)
	return result.AccessToken, nil
}

// SendMessage 发送消息的通用方法
func (wc *WecomClient) SendMessage(jsonBody []byte) error {
	return wc.send(jsonBody)
}

// GetAgentID 获取AgentID
func (wc *WecomClient) GetAgentID() int {
	return wc.config.AgentID
}

// GetAccessToken 获取AccessToken（公开方法）
func (wc *WecomClient) GetAccessToken() (string, error) {
	return wc.getAccessToken()
}

func (wc *WecomClient) send(jsonBody []byte) error {
	token, err := wc.getAccessToken()
	if err != nil {
		return err
	}

	// 发送HTTP请求（带重试逻辑）
	url := fmt.Sprintf("%s/cgi-bin/message/send?access_token=%s", wc.config.ApiDomain, token)

	resp, err := wc.httpClient.Post(url, "application/json", bytes.NewReader(jsonBody))
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("发送消息通知失败, 状态码: %d", resp.StatusCode)
	}

	var result struct {
		ErrCode int    `json:"errcode"`
		ErrMsg  string `json:"errmsg"`
	}
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return err
	}
	if result.ErrCode != 0 {
		return errors.New(result.ErrMsg)
	}
	return nil
}

// WecomUser 企业微信用户信息结构体
type WecomUser struct {
	UserID         string `json:"userid"`          // 成员UserID
	Name           string `json:"name"`            // 成员名称
	Department     []int  `json:"department"`      // 成员所属部门id列表
	Position       string `json:"position"`        // 职位信息
	Mobile         string `json:"mobile"`          // 手机号码
	Gender         string `json:"gender"`          // 性别
	Email          string `json:"email"`           // 邮箱
	Avatar         string `json:"avatar"`          // 头像url
	ThumbAvatar    string `json:"thumb_avatar"`    // 头像缩略图url
	Telephone      string `json:"telephone"`       // 座机
	Alias          string `json:"alias"`           // 成员别名
	Address        string `json:"address"`         // 地址
	OpenUserID     string `json:"open_userid"`     // 全局唯一
	MainDepartment int    `json:"main_department"` // 主部门
	Extattr        struct {
		Attrs []struct {
			Type int    `json:"type"`
			Name string `json:"name"`
			Text struct {
				Value string `json:"value"`
			} `json:"text"`
		} `json:"attrs"`
	} `json:"extattr"`
	Status           int    `json:"status"`            // 激活状态: 1=已激活，2=已禁用，4=未激活，5=退出企业
	QrCode           string `json:"qr_code"`           // 员工个人二维码
	ExternalPosition string `json:"external_position"` // 对外职务
	ExternalProfile  struct {
		ExternalCorpName string `json:"external_corp_name"`
		ExternalAttr     []struct {
			Type int    `json:"type"`
			Name string `json:"name"`
			Text struct {
				Value string `json:"value"`
			} `json:"text"`
		} `json:"external_attr"`
	} `json:"external_profile"`
}

// WecomUserListResponse 企业微信用户列表响应结构体
type WecomUserListResponse struct {
	ErrCode  int         `json:"errcode"`
	ErrMsg   string      `json:"errmsg"`
	UserList []WecomUser `json:"userlist"`
}

// GetUserList 获取企业微信用户列表（包含所有状态）
func (wc *WecomClient) GetUserList(departmentID int, fetchChild bool) ([]WecomUser, error) {
	token, err := wc.getAccessToken()
	if err != nil {
		return nil, err
	}

	// 直接调用企业微信API获取所有用户，包含所有状态
	// status=0 表示获取所有状态的用户（已激活、已禁用、未激活、退出企业）
	url := fmt.Sprintf("%s/cgi-bin/user/list?access_token=%s&department_id=%d&fetch_child=%d&status=0",
		wc.config.ApiDomain, token, departmentID, map[bool]int{true: 1, false: 0}[fetchChild])

	resp, err := wc.httpClient.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("获取用户列表失败, 状态码: %d", resp.StatusCode)
	}

	var result WecomUserListResponse
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return nil, err
	}

	if result.ErrCode != 0 {
		return nil, fmt.Errorf("获取用户列表失败: %s", result.ErrMsg)
	}

	log.Printf("成功获取 %d 个用户，包含所有状态", len(result.UserList))

	// 打印用户状态统计
	statusCount := make(map[int]int)
	for _, user := range result.UserList {
		statusCount[user.Status]++
	}

	for status, count := range statusCount {
		statusName := getStatusName(status)
		log.Printf("状态 %d (%s): %d 个用户", status, statusName, count)
	}

	return result.UserList, nil
}

// 获取状态名称
func getStatusName(status int) string {
	switch status {
	case 1:
		return "已激活"
	case 2:
		return "已禁用"
	case 4:
		return "未激活"
	case 5:
		return "退出企业"
	default:
		return "未知状态"
	}
}
